package com.prodog.command.core;

import com.prodog.command.annonations.Command;
import com.prodog.command.annonations.CommandBean;
import com.prodog.utils.bean.SpringBeanUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;

@Component
@Slf4j(topic = "游戏指令集加载器")
@Order(9999)
public class GameCommandCentral implements CommandLineRunner {
    private Map<String, Method> methodMap = new HashMap<>();
    private Map<String, Object> beanMap = new HashMap<>();
    private Map<String, List<String>> propsMap = new HashMap<>();

    @Override
    public void run(String... args) {
        this.init();
    }

    public void init() {
        log.info("正在加载游戏指令.........");
        //获取游戏指令类 初始化map
        initMap();
        log.info("游戏指令加载完毕！");
    }

    private List getCommandBeanList() {
        return SpringBeanUtils.getBeansByAnnotation(CommandBean.class);
    }

    private List<Method> getCommandMethod(Object handler) {
        Method[] methods = handler.getClass().getMethods();
        return Arrays.stream(methods).filter(method -> AnnotationUtils.findAnnotation(method, Command.class) != null).collect(Collectors.toList());
    }

    private void initMap() {
        List handlerList = getCommandBeanList();
        handlerList.forEach(handler -> {
            CommandBean commandBean = AnnotationUtils.findAnnotation(handler.getClass(), CommandBean.class);
            //获取带注解的方法
            List<Method> methodList = getCommandMethod(handler);
            methodList.forEach(method -> {
                Command command = AnnotationUtils.findAnnotation(method, Command.class);
                for (int i = 0; i < command.value().length; i++) {
                    String commandStr = command.value()[i];
                    beanMap.put(commandStr, handler);
                    methodMap.put(commandStr, method);
                    if (command.props().length >= i + 1) {
                        propsMap.put(commandStr, Arrays.asList(command.props()[i].split("\\,")));
                    } else {
                        propsMap.put(commandStr, new ArrayList<>());
                    }
                }
            });
            log.info("  指令集[" + commandBean.setName() + "]加载完成！");
        });
    }

    public String getRegexByCommandStr(String commandStr) {
        Set<Map.Entry<String, Method>> entries = methodMap.entrySet();
        for (Map.Entry<String, Method> entry : entries) {
            String regex = entry.getKey();
            if (commandStr.matches(regex)) {
                return regex;
            }
        }
        return null;
    }

    public Object getCommandBeanByRegex(String regex) {
        return beanMap.get(regex);
    }

    public Method getMethodByRegex(String regex) {
        return methodMap.get(regex);
    }

    public List<String> getPropsByRegex(String regex) {
        return propsMap.get(regex);
    }

    public Object getCommandBeanByCommandStr(String commandStr) {
        return getCommandBeanByRegex(getRegexByCommandStr(commandStr));
    }

    public Method getMethodByCommandStr(String commandStr) {
        return getMethodByRegex(getRegexByCommandStr(commandStr));
    }

    public List<String> getPropsByCommandStr(String commandStr) {
        return getPropsByRegex(getRegexByCommandStr(commandStr));
    }
}
